﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIA.HwAccess;
using SIA.Configurators;

namespace SIA.Allarms
{
    public abstract class AbstractAllarm : IAllarm
    {
        // Attributi e Metodi Astratti
        public abstract Boolean isActive { get; }
        public abstract IAllarm clone();

        //Eventi
        public event AllarmEvent RiseONAllarm;
        public event AllarmEvent RiseOFFAllarm;
        public event AllarmEvent RiseACKAllarm;
        public event AllarmEvent RiseIsArchiviableAllarm;
       
        // Variabili        
        protected readonly string _nome;
        protected readonly string _gruppo;
        protected readonly string _commento;
        protected readonly IHwSignal _signal;
        protected readonly string _regExp;
        protected Nullable<DateTime> _dataOraON = null;
        protected Nullable<DateTime> _dataOraOFF = null;
        protected Nullable<DateTime> _dataOraACK = null;

        protected bool _isActive = false;

        // Attributti
        public String Nome { get { return this._nome; } }
        public String Gruppo { get { return this._gruppo; } }
        public String Commento { get { return this._commento; } }
        public IHwSignal Signal { get { return this._signal; } }
        public Nullable<DateTime> DataOraON { get { return this._dataOraON; } }
        public Nullable<DateTime> DataOraOFF { get { return this._dataOraOFF; } }
        public Nullable<DateTime> DataOraACK { get { return this._dataOraACK; } }        
        /// <summary>è archiviabile quando ho la data di ON di OFF e di ACK</summary>
        public Boolean isArchiviable { get { return _dataOraACK != null && _dataOraOFF != null && _dataOraON != null; } }        

        /// <summary>Costruttore standard</summary>
        /// <param name="nomeAllarme"></param>
        /// <param name="gruppo"></param>
        /// <param name="commento"></param>
        /// <param name="Signal"></param>
        /// <param name="regExp"></param>
        public AbstractAllarm(IDictionaryProperty allarmProperty, IHwSignal signal)
            :this(allarmProperty["NOMEALLARME"].PropertyValue, allarmProperty["GRUPPO"].PropertyValue, allarmProperty["COMMENTO"].PropertyValue,
                        allarmProperty["ALLARMSTATE"].PropertyValue, signal){}
        private AbstractAllarm(String nome, String gruppo, String commento, String regExp, IHwSignal signal)
        {
            this._nome = nome;
            this._gruppo = gruppo;
            this._commento = commento;
            this._signal = signal;
            this._regExp = regExp;

            signal.ValueChange += new SignalEvent(signal_ValueChangeEvent);
        }
        
        void signal_ValueChangeEvent(IHwSignal signal)
        {
            Boolean _lastIsActive = _isActive;
            _isActive = this.isActive;

            if (_isActive && !_lastIsActive && _dataOraON == null)
            {
                this._dataOraON = DateTime.Now;
                if (this.RiseONAllarm!=null) this.RiseONAllarm(this);
            }
            if (!_isActive && _lastIsActive && _dataOraON != null && _dataOraOFF == null)
            {
                this._dataOraOFF = DateTime.Now;
                if (this.RiseOFFAllarm != null) this.RiseOFFAllarm(this);                    
            }
            if (this.isArchiviable)
                if (this.RiseIsArchiviableAllarm!=null) this.RiseIsArchiviableAllarm(this);
        }       
                 
        /// <summary>invio del segnale ACK all'allarme</summary>
        public void sendACK()
        {
            if (this._dataOraACK == null && _dataOraON != null)   //Solo il primo e se l'allarme è attivo
            {               
                this._dataOraACK = DateTime.Now;
                if (this.RiseACKAllarm != null) this.RiseACKAllarm(this);
            }
            if (this.isArchiviable)
                if (this.RiseIsArchiviableAllarm!=null) this.RiseIsArchiviableAllarm(this);
        }

        /// <summary>Reset stato allarme</summary>
        public void clean()
        {
            this._dataOraON = null;
            this._dataOraOFF = null;
            this._dataOraACK = null;
        }

        public override string ToString()
        {
            return this._nome + ": " + isActive.ToString();
        }        
    }
}
